package com.andnnl.vcode;

import javax.imageio.ImageIO;
import javax.net.ssl.HttpsURLConnection;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Created by chenss on 2020/11/24.
 */
public class ImageDisturbTest {

    public static void main(String[] args) throws Exception {


        //保存验证码的文件夹
        File imgFile = new File("C:\\Users\\pc\\Desktop\\formPic\\unFormPic");
        //验证码保存地址
        String downAddress = "D:\\vcode3\\";
        //验证码下载地址
        String downURL = "https://gzh.szjj.sz.gov.cn/imgValidCode.do?51";
//            for (int i = 1; i <= 1000; i++) {
////                downloadPic(downURL, downAddress + i + ".jpg");
//                HttpsDownloadUtils.downloadFile(downURL, downAddress + (""+(i+10000)).substring(1,5) + ".jpg");
//                Thread.sleep(10 + (i % 100));
//            }


        String fileName = "picture";
        String outPath="D:\\vcode4";
        File dir=new File("D:\\vcode3");
        for (File file : dir.listFiles()) {
            if(!file.getName().endsWith(".jpg")) continue;
            handleImg(file,outPath);
        }

    }
    /**
     * 下载验证码
     *
     * @param picUrl
     *            验证码获取地址
     * @param address
     *            图片保存地址
     */
    public static void downloadPic(String picUrl, String imgAddress) {
        try {
            URL url = new URL(picUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            //需要设置头信息，否则会被识别为机器而获取不到验证码图片
            conn.setRequestProperty("User-Agent",
                    "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36");
            conn.connect();

            int result = -1;
            byte[] buf = new byte[1024];
            BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
            FileOutputStream fos = new FileOutputStream(imgAddress);
            while ((result = bis.read(buf)) != -1) {
                fos.write(buf);
            }
            fos.flush();

            fos.close();
            bis.close();
            System.out.println("图片下载成功");
        } catch (MalformedURLException e) {
            System.out.println("图片读取失败");
            e.printStackTrace();
        } catch (IOException e) {
            System.out.println();
            e.printStackTrace();
        }
    }
    private static void handleImg(File file,String outPath) throws IOException {
        BufferedImage img = ImageIO.read(file);
        int width = img.getWidth();
        int height = img.getHeight();

        //背景颜色变白色
//        removeBg(img);

        //灰度+二值
        grayImg(img);

        //去掉边框几个像素厚度
        int fix=2;
        delBorder(img,5,10);

        //去掉多余的干扰线
        denoiseLine(img);


        String pathname = outPath+File.separator+file.getName();
        writeImg(img, pathname);
    }

    /**
     * 背景颜色变白色
     * @param img
     */
    private static void removeBg(BufferedImage img) {
        int width = img.getWidth();
        int height = img.getHeight();
        for (int i = 1; i < width; i++) {
            Color colorFirst = new Color(img.getRGB(i, 1));
            int numFirstGet = colorFirst.getRed() + colorFirst.getGreen() + colorFirst.getBlue();
            for (int x = 0; x < width; x++) {
                for (int y = 0; y < height; y++) {
                    int rgb = img.getRGB(x, y);
                    Color color = new Color(rgb);
//                    System.out.println("red:" + color.getRed() + " | green:" + color.getGreen() + " | blue:" + color.getBlue());
                    int num = color.getRed() + color.getGreen() + color.getBlue();
                    if (num >= numFirstGet) {
                        img.setRGB(x, y, Color.WHITE.getRGB());
                    }
                }
            }
        }
    }

    /**
     * 去掉边框几个像素厚度
     * @param img
     * @param fixUD 上下边框
     * @param fixLR 左右边框
     */
    private static void delBorder(BufferedImage img, int fixUD, int fixLR) {
        int width = img.getWidth();
        int height = img.getHeight();
        for (int x = 0; x < width; x++) {
            for (int i = 0; i < fixUD; i++) {
                img.setRGB(x, i, Color.WHITE.getRGB());
                img.setRGB(x, height-i-1, Color.WHITE.getRGB());
            }
        }
        for (int y = 0; y < height; y++) {
            for (int i = 0; i < fixLR; i++) {
                img.setRGB(i, y, Color.WHITE.getRGB());
                img.setRGB(width-i-1, y, Color.WHITE.getRGB());
            }
        }
    }

    public static BufferedImage denoiseLine(BufferedImage img) {
        int w = img.getWidth();
        int h = img.getHeight();
//        int white = new Color(255, 255, 255).getRGB();
        int xx = 535;
        for (int x = 1; x < w - 1; x++) {
            for (int y = 1; y < h - 1; y++) {
                int count = 0;

                if (getRGBCount(img, x, y - 1) > xx)
                    count++;
                if (getRGBCount(img, x, y + 1) > xx)
                    count++;
                if (getRGBCount(img, x - 1, y) > xx)
                    count++;
                if (getRGBCount(img, x + 1, y) > xx)
                    count++;
                if (count > 2)
                    img.setRGB(x, y, Color.WHITE.getRGB());

//                if img[x, y - 1] > xx:
//                count = count + 1
//                if img[x, y + 1] > xx:
//                count = count + 1
//                if img[x - 1, y] > xx:
//                count = count + 1
//                if img[x + 1, y] > xx:
//                count = count + 1
//                if count > 2:
//                img[x, y] = 255
            }

        }
        return img;
    }




    private static int getRGBCount(BufferedImage img, int x, int y) {
        Color color = new Color(img.getRGB(x, y));
        return color.getRed() + color.getGreen() + color.getBlue();
    }


    public static void grayImg(BufferedImage img){
        int width = img.getWidth();
        int  height = img.getHeight();
        int area = width * height;
        int gray[][] = new int[width][height];
        int u = 0;// 灰度平均值
        int graybinary;
        int graysum = 0;
        int graymean = 0;
        int grayfrontmean = 0;
        int graybackmean = 0;
        Color color;
        int pixl[][] = new int[width][height];
        int pixelsR;
        int pixelsG;
        int pixelsB;
        int pixelGray;
        int T = 0;
        int front = 1;
        int back = 0;
        for (int i = 1; i < width; i++) { // 不算边界行和列，为避免越界
            for (int j = 1; j < height; j++) {
                pixl[i][j] = img.getRGB(i, j);
                color = new Color(pixl[i][j]);
                pixelsR = color.getRed();// R空间
                pixelsB = color.getBlue();// G空间
                pixelsG = color.getGreen();// B空间
                pixelGray = (int) (0.3 * pixelsR + 0.59 * pixelsG + 0.11 * pixelsB);// 计算每个坐标点的灰度
                gray[i][j] = (pixelGray << 16) + (pixelGray << 8) + (pixelGray);
                graysum += pixelGray;
            }
        }
        graymean = (int) (graysum / area);// 整个图的灰度平均值
        u = graymean;
//        System.out.println(u);
        for (int i = 0; i < width; i++) // 计算整个图的二值化阈值
        {
            for (int j = 0; j < height; j++) {
                if (((gray[i][j]) & (0x0000ff)) < graymean) {
                    graybackmean += ((gray[i][j]) & (0x0000ff));
                    back++;
                } else {
                    grayfrontmean += ((gray[i][j]) & (0x0000ff));
                    front++;
                }
            }
        }
        int frontvalue = (int) (grayfrontmean / front);// 前景中心
        int backvalue = (int) (graybackmean / back);// 背景中心
        float G[] = new float[frontvalue - backvalue + 1];// 方差数组
        int s = 0;
//        System.out.println(front);
//        System.out.println(frontvalue);
//        System.out.println(backvalue);
        for (int i1 = backvalue; i1 < frontvalue + 1; i1++)// 以前景中心和背景中心为区间采用大津法算法
        {
            back = 0;
            front = 0;
            grayfrontmean = 0;
            graybackmean = 0;
            for (int i = 0; i < width; i++) {
                for (int j = 0; j < height; j++) {
                    if (((gray[i][j]) & (0x0000ff)) < (i1 + 1)) {
                        graybackmean += ((gray[i][j]) & (0x0000ff));
                        back++;
                    } else {
                        grayfrontmean += ((gray[i][j]) & (0x0000ff));
                        front++;
                    }
                }
            }
            grayfrontmean = (int) (grayfrontmean / front);
            graybackmean = (int) (graybackmean / back);
            G[s] = (((float) back / area) * (graybackmean - u)
                    * (graybackmean - u) + ((float) front / area)
                    * (grayfrontmean - u) * (grayfrontmean - u));
            s++;
        }
        float max = G[0];
        int index = 0;
        for (int i = 1; i < frontvalue - backvalue + 1; i++) {
            if (max < G[i]) {
                max = G[i];
                index = i;
            }
        }
        // System.out.println(G[index]);
        // System.out.println(index);
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                if (((gray[i][j]) & (0x0000ff)) < (index + backvalue)) {
                    img.setRGB(i, j, 0x000000);
                } else {
                    img.setRGB(i, j, 0xffffff);
                }
            }
        }
//        File f = new File("F:/88.jpg");
//        ImageIO.write(outBinary, "jpg", f);
    }

    private static void writeImg(BufferedImage img, String pathname) throws IOException {
        File file = new File(pathname);
        if (!file.exists()) {
            File dir = file.getParentFile();
            if (!dir.exists()) {
                dir.mkdirs();
            }
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        ImageIO.write(img, "jpg", file);
    }
}
